import { Injectable, NotFoundException, UnauthorizedException, BadRequestException } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CreateMessageDto } from './dto/create-message.dto';
import { formatBeijingISO } from '../common/date.util';
import { MessageRole } from '@prisma/client';
import { AIService, AIMessage } from '../ai/ai.service';

@Injectable()
export class MessageService {
  constructor(
    private prisma: PrismaService,
    private aiService: AIService,
  ) {}

  // Create message and generate AI response
  async create(userId: string, createMessageDto: CreateMessageDto) {
    const { sessionId, content, metadata } = createMessageDto;

    // Verify session exists and belongs to current user
    const session = await this.prisma.session.findFirst({
      where: { id: sessionId, userId },
      select: { id: true, personaId: true, skill: true, personaSnapshot: true },
    });

    if (!session) {
      throw new NotFoundException(`Session with ID ${sessionId} not found or access denied`);
    }

    // Create user message
    const userMessage = await this.prisma.message.create({
      data: {
        sessionId,
        role: MessageRole.USER,
        content,
        metadata: metadata || { type: 'text', source: 'user' },
      },
      select: {
        id: true,
        role: true,
        content: true,
        metadata: true,
        createdAt: true,
      },
    });

    // Generate AI response
    let aiContent: string;
    let aiMetadata: any = { type: 'text', source: 'ai', model: 'gpt-4o-mini' };

    try {
      // Get session history messages for context
      const recentMessages = await this.prisma.message.findMany({
        where: { sessionId },
        orderBy: { createdAt: 'desc' },
        take: 10,
        select: {
          role: true,
          content: true,
        },
      });

      // Build AI message history
      const aiMessages: AIMessage[] = recentMessages
        .reverse()
        .map(msg => ({
          role: msg.role === MessageRole.USER ? 'user' : 'assistant',
          content: msg.content,
        }));

      // Add current user message
      aiMessages.push({
        role: 'user',
        content,
      });

      // Get persona prompt
      const personaSnapshot = session.personaSnapshot as any;
      const personaPrompt = personaSnapshot?.systemPrompt || 
        'You are a friendly AI assistant, please reply to user questions in English.';

      // Generate AI response
      const aiResponse = await this.aiService.generateResponse(
        aiMessages,
        personaPrompt,
        'qwen-turbo'
      );

      aiContent = aiResponse.content;
      aiMetadata = {
        type: 'text',
        source: 'ai',
        model: aiResponse.model,
        usage: aiResponse.usage,
      };
    } catch (error) {
      // Fallback handling when AI service fails
      aiContent = `Sorry, I cannot reply to your message "${content}" right now. Please try again later.`;
      aiMetadata = {
        type: 'text',
        source: 'ai',
        model: 'fallback',
        error: 'AI service unavailable',
      };
    }

    const aiResponse = await this.prisma.message.create({
      data: {
        sessionId,
        role: MessageRole.ASSISTANT,
        content: aiContent,
        metadata: aiMetadata,
      },
      select: {
        id: true,
        role: true,
        content: true,
        metadata: true,
        createdAt: true,
      },
    });

    // Update session updatedAt
    await this.prisma.session.update({
      where: { id: sessionId },
      data: { updatedAt: new Date() },
    });

    return {
      userMessage: {
        ...userMessage,
        createdAt: formatBeijingISO(userMessage.createdAt),
      },
      aiResponse: {
        ...aiResponse,
        createdAt: formatBeijingISO(aiResponse.createdAt),
      },
    };
  }

  // Get session message list
  async getBySessionId(userId: string, sessionId: string, page: number, pageSize: number, order: 'asc' | 'desc') {
    // Verify session permissions
    const session = await this.prisma.session.findFirst({
      where: { id: sessionId, userId },
      select: { id: true },
    });

    if (!session) {
      throw new NotFoundException(`Session with ID ${sessionId} not found or access denied`);
    }

    const skip = (page - 1) * pageSize;
    const take = pageSize;

    const [messages, total] = await Promise.all([
      this.prisma.message.findMany({
        where: { sessionId },
        orderBy: { createdAt: order },
        skip,
        take,
        select: {
          id: true,
          role: true,
          content: true,
          metadata: true,
          createdAt: true,
        },
      }),
      this.prisma.message.count({
        where: { sessionId },
      }),
    ]);

    return {
      items: messages.map(msg => ({
        ...msg,
        createdAt: formatBeijingISO(msg.createdAt),
      })),
      total,
      page,
      pageSize,
    };
  }

  // Get latest session messages
  async getLatestMessages(userId: string, sessionId: string, limit: number = 10) {
    // Verify session permissions
    const session = await this.prisma.session.findFirst({
      where: { id: sessionId, userId },
      select: { id: true },
    });

    if (!session) {
      throw new NotFoundException(`Session with ID ${sessionId} not found or access denied`);
    }

    const messages = await this.prisma.message.findMany({
      where: { sessionId },
      orderBy: { createdAt: 'desc' },
      take: limit,
      select: {
        id: true,
        role: true,
        content: true,
        metadata: true,
        createdAt: true,
      },
    });

    return messages.reverse().map(msg => ({
      ...msg,
      createdAt: formatBeijingISO(msg.createdAt),
    }));
  }
}
